type browser = {
  browser: 'chrome' | 'edge' | 'safari' | 'firefox'
  os: 'ios' | 'android' | 'windows' | 'macos' | 'linux'
  // 与编译条件一致，例如H5
  platform: string
  language: string
}

export function getBrowser(): browser {
  const sys = uni.getSystemInfoSync()
  var browser = {
    browser: sys.browserName,
    os: sys.osName,
    platform: sys.uniPlatform,
    language: sys.hostLanguage
  }
  return browser
}

/**
 * 数据深拷贝
 * @param {Object}
 * @return {Object}
 */
export function deepCopy(obj) {
  if (obj === null || typeof obj !== 'object') {
    return obj
  }
  const newObj = obj instanceof Array ? [] : {}
  for (const key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      newObj[key] = deepCopy(obj[key])
    }
  }
  return newObj
}
/**
 * 防抖
 * @param {funtion}
 * @param {number}
 * @return {undefined}
 */
export function debounce(fn, delay, _this) {
  var delay = delay || 200
  var timer = null
  return function (...args) {
    const self = _this || this
    timer && clearTimeout(timer)
    timer = setTimeout(function () {
      timer = null
      fn.apply(self, args)
    }, delay)
  }
}
/**
 * 节流
 * @param {funtion}
 * @param {number}
 * @param {boolean} 是否间隔时间之后再执行
 * @return {undefined}
 */
export function throttle(fn, delay, path = false) {
  var last
  var timer
  var interval = delay || 200
  return function (...args) {
    const self = this
    const now = +new Date()
    if (last && now - last < delay) {
      if (path) {
        clearTimeout(timer)
        timer = setTimeout(function () {
          last = now
          fn.apply(self, args)
        }, delay)
      }
    } else {
      last = now
      fn.apply(self, args)
    }
  }
}
/**
 * 判断类型
 * @param {any}
 * @return {string}
 */
export function typeOf(argu) {
  const map = {
    '[object Number]': 'number',
    '[object String]': 'string',
    '[object Boolean]': 'boolean',
    '[object Undefined]': 'undefined',
    '[object Null]': 'null',
    '[object Array]': 'array',
    '[object Arguments]': 'arguments',
    '[object Function]': 'function',
    '[object Error]': 'error',
    '[object Date]': 'date',
    '[object RegExp]': 'regexp',
    '[object Object]': 'object'
  }
  const str = Object.prototype.toString.call(argu)
  return map[str]
}
/**
 * 获取当前页面实例
 * @param {number}
 * @return {object}
 */
export function getPage(index) {
  const pageList = getCurrentPages()
  if (typeOf(index) === 'number' && index >= 0 && index < pageList.length) {
    return pageList[pageList.length - 1 - index]
  } else if (typeOf(index) === 'undefined') {
    return pageList[pageList.length - 1]
  } else if (typeOf(index) !== 'number') {
    throw TypeError('参数不正确!')
  } else {
    throw Error('不存在该页面!')
  }
}
/**
 * 生成uuid
 * @return {string}
 */
export function Uuid() {
  var s = []
  var hexDigits = '0123456789abcdef'
  for (var i = 0; i < 36; i++) {
    s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1)
  }
  s[14] = '4' // bits 12-15 of the time_hi_and_version field to 0010
  s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1) // bits 6-7 of the clock_seq_hi_and_reserved to 01
  s[8] = '-'
  s[13] = '-'
  s[18] = '-'
  s[23] = '-'

  var uuid = s.join('')
  return uuid
}
/**
 * 获取当前系统时间
 * @return {string}
 */
export function getDate(format = 'YY-MM-DD') {
  const date = new Date()
  const year = date.getFullYear()
  const m = date.getMonth() + 1
  const mm = date.getMonth() < 9 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1
  const d = date.getDate()
  const dd = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
  const weekMap = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
  const week = weekMap[date.getDay()]
  const hours = date.getHours() < 9 ? '0' + date.getHours() : date.getHours()
  const minutes = date.getMinutes() < 9 ? '0' + date.getMinutes() : date.getMinutes()
  const seconds = date.getSeconds() < 9 ? '0' + date.getSeconds() : date.getSeconds()
  const map = {
    YY: year,
    MM: mm,
    M: m,
    DD: dd,
    D: d,
    W: week,
    hh: hours,
    mm: minutes,
    ss: seconds
  }
  return format.replace(/[YMDWhms]+/g, (v) => {
    return map[v]
  })
}
/**
 * Parse the time to string
 * @param {(Object|string|number)} time
 * @param {string} cFormat
 * @returns {string | null}
 */
export function parseTime(time, cFormat) {
  if (arguments.length === 0 || time === '') {
    return null
  }
  const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
  let date
  if (typeof time === 'object') {
    date = time
  } else {
    if (typeof time === 'string') {
      if (/^[0-9]+$/.test(time)) {
        // support "1548221490638"
        time = parseInt(time)
      } else {
        // support safari
        // https://stackoverflow.com/questions/4310953/invalid-date-in-safari
        time = time.replace(new RegExp(/-/gm), '/')
      }
    }

    if (typeof time === 'number' && time.toString().length === 10) {
      time = time * 1000
    }
    date = new Date(time)
  }
  const formatObj = {
    y: date.getFullYear(),
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes(),
    s: date.getSeconds(),
    a: date.getDay()
  }
  const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
    const value = formatObj[key]
    // Note: getDay() returns 0 on Sunday
    if (key === 'a') {
      return ['日', '一', '二', '三', '四', '五', '六'][value]
    }
    return value.toString().padStart(2, '0')
  })
  return time_str
}
/**
 * @description : 校验身份证号是否合规（18位、15位）
 * @param        {String|Number} value
 * @return       {Boolean} true-合规 false-不合规
 */
export function validatorIdcard(value) {
  const psidno = String(value)
  // 1.校验身份证号格式和长度
  const regPsidno =
    /^(^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$)|(^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[X])$)$/
  if (!regPsidno.test(psidno)) {
    return false
  }
  // 2.校验前两位的省份编码是否正确
  const province = {
    11: '北京',
    12: '天津',
    13: '河北',
    14: '山西',
    15: '内蒙古',
    21: '辽宁',
    22: '吉林',
    23: '黑龙江 ',
    31: '上海',
    32: '江苏',
    33: '浙江',
    34: '安徽',
    35: '福建',
    36: '江西',
    37: '山东',
    41: '河南',
    42: '湖北 ',
    43: '湖南',
    44: '广东',
    45: '广西',
    46: '海南',
    50: '重庆',
    51: '四川',
    52: '贵州',
    53: '云南',
    54: '西藏 ',
    61: '陕西',
    62: '甘肃',
    63: '青海',
    64: '宁夏',
    65: '新疆',
    71: '台湾',
    81: '香港',
    82: '澳门',
    91: '国外'
  }
  if (!province[Number(psidno.slice(0, 2))]) {
    return false
  }
  // 3.校验出生日期
  if (psidno.length === 15) {
    // 15位号码 省（2位）市（2位）县（2位）年（2位）月（2位）日（2位）校验码（3位）
    const reg = new RegExp(/^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/)
    const arrSplit = psidno.match(reg)
    // 15位号码在年份前补 19 或 20
    const year = Number(arrSplit[2].charAt(0)) > 0 ? '19' + arrSplit[2] : '20' + arrSplit[2]
    const month = arrSplit[3]
    const day = arrSplit[4]
    if (!validateBirthday(year, month, day)) {
      return false
    }
  } else if (psidno.length === 18) {
    // 18位号码 省（2位）市（2位）县（2位）年（4位）月（2位）日（2位）校验码（4位）
    const reg = new RegExp(/^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/)
    const arrSplit = psidno.match(reg)
    const year = arrSplit[2]
    const month = arrSplit[3]
    const day = arrSplit[4]
    if (!validateBirthday(year, month, day)) {
      return false
    }
  } else {
    return false
  }
  // 校验出生日期是否合理
  function validateBirthday(year, month, day) {
    year = Number(year) // 年
    month = Number(month) // 月
    day = Number(day) // 日
    const nowTime = new Date().getTime() // 当前时间戳
    const birthTime = new Date(`${year}-${month}-${day}`).getTime() // 获取出生日期的时间戳
    // 不能是明天出生的吧
    if (birthTime > nowTime) {
      return false
    }
    // 一般人活不到150岁吧
    const nowYear = new Date().getFullYear()
    if (nowYear - year > 150) {
      return false
    }
    // 不能是13月出生的吧
    if (month < 1 || month > 12) {
      return false
    }
    // 不能是2月30号、4月31号、5月32号出生的吧
    const date = new Date(year, month, 0) // 获取当月的最后一天
    if (day < 1 || day > date.getDate()) {
      return false
    }
    return true
  }
  // 4.18位号码校验生成的校验码
  if (psidno.length === 18) {
    const Wi = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2] // 加权因子
    const parity = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'] // 校验码
    let sum = 0
    for (let i = 0; i < 17; i++) {
      sum += Number(psidno.charAt(i)) * Wi[i]
    }
    if (parity[sum % 11] !== psidno[17]) {
      return false
    }
  }
  return true
}

export function ObjectOwn(obj, key) {
  return Object.prototype.hasOwnProperty.call(obj, key)
}
